/*
 * Copyright 2014 Christian Hildebrandt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.sisoft.timera.beans;

import java.io.IOException;
import java.io.Serializable;
import java.util.ResourceBundle;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import de.sisoft.timera.entity.Employee;
import de.sisoft.timera.entity.Role;
import de.sisoft.timera.exception.IncorrectPasswordException;
import de.sisoft.timera.exception.UserNotFoundException;
import de.sisoft.timera.service.LoginService;

@ManagedBean
@SessionScoped
public class LoginBean implements Serializable {

    private static final long serialVersionUID = 6588915912071764472L;

    @Inject
    private LoginService loginService;

    private String username;
    private String password;
    private boolean rememberMe;

    private Employee logggedInUser;
    private boolean loggedIn;

    @ManagedProperty("#{msg}")
    private ResourceBundle bundle;

    /**
     * @return the bundle
     */
    public ResourceBundle getBundle() {
	return bundle;
    }

    /**
     * @return the logggedInUser
     */
    public Employee getLogggedInUser() {
	return logggedInUser;
    }

    /**
     * @return the password
     */
    public String getPassword() {
	return password;
    }

    /**
     * @return the username
     */
    public String getUsername() {
	return username;
    }

    /**
     * @return the loggedIn
     */
    public boolean isLoggedIn() {
	return loggedIn;
    }

    /**
     * @return the rememberMe
     */
    public boolean isRememberMe() {
	return rememberMe;
    }

    /**
     * Logs in a user by lookup for username/password in database. If the given
     * user could not be found a UserNotFoundException is cought and a localized
     * message written to faces context. If the user entered a wrong password
     * also a message is written to faces context. Only if the user exists and
     * the password is correct the user is redirected to the timesheet page.
     *
     * @return null if authorization fails, timesheet page else.
     */
    public String login() {
	try {

	    logggedInUser = loginService.isAuthorized(username, password);
	    loggedIn = true;
	    // role based redirect via faces-config
	    if (logggedInUser.hasRole(Role.ADMIN)) {
		return "admin-success";
	    } else {
		return "employee-success";
	    }
	} catch (final UserNotFoundException unfe) {
	    Logger.getLogger(LoginBean.class.getName()).log(Level.ERROR, unfe.getMessage(), unfe);
	    addErrorMessage("User faslch", null, null);
	    // addErrorMessage(null, "login.wrong.username", null);
	} catch (final IncorrectPasswordException ipe) {
	    addErrorMessage("Passwort falsch", null, null);
	    // addErrorMessage(null, "login.wrong.password", null);
	    Logger.getLogger(LoginBean.class.getName()).log(Level.ERROR, ipe.getMessage(), ipe);
	}
	loggedIn = false;
	return null;
    }

    public void logout() {
	// Invalidate session of a sessionscoped managed bean
	FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
	try {
	    // Redirect to page you want after logout
	    final ExternalContext serverContext = FacesContext.getCurrentInstance().getExternalContext();
	    serverContext.redirect(serverContext.getRequestContextPath() + "/login.xhtml");

	} catch (final IOException ex) {
	    Logger.getLogger(LoginBean.class.getName()).log(Level.ERROR, null, ex);
	}
    }

    private void addErrorMessage(String message, final String resourceMessageKey, final String clientId) {
	FacesMessage facesMessage = new FacesMessage();
	final FacesContext facesContext = FacesContext.getCurrentInstance();

	if (StringUtils.isEmpty(message) && !StringUtils.isEmpty(resourceMessageKey)) {
	    final ResourceBundle bundle = facesContext.getApplication().getResourceBundle(facesContext, "msg");
	    message = bundle.getString(resourceMessageKey);
	} else {
	    facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
	}
	facesContext.addMessage(clientId, facesMessage);
    }

    /**
     * @param bundle
     *            the bundle to set
     */
    public void setBundle(final ResourceBundle bundle) {
	this.bundle = bundle;
    }

    /**
     * @param loggedIn
     *            the loggedIn to set
     */
    public void setLoggedIn(final boolean loggedIn) {
	this.loggedIn = loggedIn;
    }

    /**
     * @param logggedInUser
     *            the logggedInUser to set
     */
    public void setLogggedInUser(final Employee logggedInUser) {
	this.logggedInUser = logggedInUser;
    }

    /**
     * @param password
     *            the password to set
     */
    public void setPassword(final String password) {
	this.password = password;
    }

    /**
     * @param rememberMe
     *            the rememberMe to set
     */
    public void setRememberMe(final boolean rememberMe) {
	this.rememberMe = rememberMe;
    }

    /**
     * @param username
     *            the username to set
     */
    public void setUsername(final String username) {
	this.username = username;
    }

}
